#ifndef BINARIA_CUH
#define BINARIA_CUH

//Incluyo la clase Random para la generación de números aleatorios en CUDA
#include "../utils/Random.cu"

/****************** Representacion binaria ********************/

/******************* Declaracion de Funciones del Host *************************/
void representacionBinaria();

void traerImprimirBinaria(float* fitnessHost, float* fitnessDevice, int tamVectorFitnessFloat, bool* poblacionHost, bool* poblacionDevice, int tamVectorPoblacion, int iteracion);
void traerImprimirMejorIndividuoBinaria(float* mejorFitnessIndividuoGPU, float* mejorFitnessIndividuoGPUDevice, int tamVectorFitnessMejoresIndividuosGPU, bool* mejorIndividuoGPU, bool* mejorIndividuoGPUDevice, int tamVectorMejoresIndividuosGPU, int iteracion);

/******************* Declaracion de Funciones Global del Device ********************/

__global__ void inicializarPoblacionBinaria(bool* poblacion, float* fitnessActualDevice, struct Random randomGPU, int cantCromosomasPoblacion, float* fitnessOrdenadoDevice);
__global__ void mainKernelBinaria(bool* poblacionActualDevice, bool* nuevaPoblacionDevice, float* fitnessActualDevice, float* nuevoFitnessDevice, int* poblacionActualAcambiarDevice, int*  nuevaPoblacionAcambiarDevice, bool* individuosAMigrarDevice, bool * individuoAMigrarGPUaCPUdevice, float* probabilidadRuletaDevice, float* fitnessTotalParaRuletaDevice, struct Random r, float* fitnessOrdenadoDevice, int* vectorIndicesFitnessOrdenado, int iteracion, bool* mejorIndividuoGPUDevice, float* mejorFitnessIndividuoGPUDevice);
__global__ void migracionRepresentacionBinaria(bool* poblacionActualDevice, float* fitnessActualDevice, bool* individuosAMigrarDevice, struct Random randomGPU, bool* individuoAMigrarCPUaGPUdevice);

/******************* Declaracion de Funciones internas del Device *****************/

__device__ int obtenerMejorIndividuoBinaria(float* vectorFitness);
__device__ void obtenerPeorIndividuoBinaria(float* vectorFitness, int indices[2]);

__global__ void migracionRepresentacionBinaria(bool* poblacionActualDevice, float* fitnessActualDevice, bool* individuosAMigrarDevice, struct Random randomGPU, bool* individuoAMigrarCPUaGPUdevice);
__global__ void obtenerMejoresIndividuosBinaria(bool* poblacion, float* fitness, bool* mejorIndividuoDevice, float* mejorFitnessIndividuoGPUDevice);
__device__ void individosAMigrarRepresentacionBinaria(float* nuevoFitnessDevice, bool* nuevaPoblacionDevice, bool* individuosAMigrarDevice, bool * individuoAMigrarGPUaCPUdevice);

__device__ void asignarProbabilidadRuletaBinaria(float* fitnessActualDevice, float* probabilidadRuletaBinaria, float* fitnessTotalParaRuletaDevice, struct Random randomGPU);

__device__ int seleccionBinaria(float* vectorFitness, float* probabilidadRuletaDevice, struct Random randomGPU, int ejecutarFuncion, int* vectorIndicesFitnessOrdenado);
__device__ int seleccionPorTorneoBinaria(float* vectorFitness, struct Random randomGPU);
__device__ int seleccionPorRangoBinaria(int* vectorIndicesFitnessOrdenado, struct Random randomGPU);
__device__ int seleccionRuedaRuletaBinaria(float* probabilidadRuletaDevice, struct Random randomGPU);

__device__ void cruzamientoRepresentacionBinaria(bool* poblacionActual, bool* nuevaPoblacion, int posicionCromosoma1, int posicionCromosoma2, float probabilidad, struct Random randomGPU, int ejecutarFuncion);
__device__ void cruzamientoCromosoma1PuntoBinaria(bool* poblacionActual, bool* nuevaPoblacion, int posicionCromosoma1, int posicionCromosoma2, float probabilidad, struct Random randomGPU);
__device__ void cruzamientoCromosoma2PuntosBinaria(bool* poblacionActual, bool* nuevaPoblacion, int posicionCromosoma1, int posicionCromosoma2, float probabilidad, struct Random randomGPU);
__device__ void cruzamientoCromosomaUniformeBinaria(bool* poblacionActual, bool* nuevaPoblacion, int posicionCromosoma1, int posicionCromosoma2, float probabilidad, struct Random randomGPU);

__device__ void mutacionBinaria(bool* poblacion, float probabilidad, struct Random randomGPU, int ejecutarFuncion);
__device__ void mutacionPorInversion(bool* poblacion, float probabilidad, struct Random randomGPU);

__device__ void asignarFitnessBinaria(bool* nuevaPoblacion, float* nuevoVectorFitness, float* fitnessOrdenadoDevice);

__device__ void reemplazoBinaria(bool* poblacionActualDevice, bool* nuevaPoblacionDevice, int* poblacionActualAcambiar, int* nuevaPoblacionAcambiar, float * fitnessActualDevice, float* nuevoFitnessDevice, int ejecutarFuncion);
__device__ void reemplazoElitistaBinaria(bool* poblacionActual, bool* nuevaPoblacion, int* poblacionActualAcambiar, int* nuevaPoblacionAcambiar, float * fitnessActual, float* nuevoFitness);

#endif

